package ch.ti.bfh.app.loodel.web.controller;

import ch.ti.bfh.app.loodel.service.create.CreateTimeSlotData;
import ch.ti.bfh.app.loodel.service.create.ShowTimeSlotLocationData;
import ch.ti.bfh.app.loodel.service.create.TimeSlotVoteSearchService;
import ch.ti.bfh.app.loodel.web.model.CreateTimeSlotDataWrapper;
import ch.ti.bfh.app.loodel.web.model.CreateTimeSlotModel;
import ch.ti.bfh.app.loodel.web.utils.InvalidDateInvtervalException;
import org.apache.commons.lang.time.DateUtils;
import org.joda.time.DateTime;
import org.joda.time.Interval;
import org.joda.time.Period;
import org.primefaces.event.*;
import org.primefaces.model.DefaultScheduleEvent;
import org.primefaces.model.ScheduleEvent;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import javax.inject.Inject;
import java.io.Serializable;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

@Component
@Scope("request")
public class TimeSlotCreateController implements Serializable {

    private CreateTimeSlotModel createTimeSlotModel;

    private TimeSlotVoteSearchService timeSlotVoteSearchService;

    @Inject
    public TimeSlotCreateController(CreateTimeSlotModel createTimeSlotModel, TimeSlotVoteSearchService timeSlotVoteSearchService) {
        this.createTimeSlotModel = createTimeSlotModel;
        this.timeSlotVoteSearchService = timeSlotVoteSearchService;

    }

    public void init() {
        createTimeSlotModel.reset();
        createTimeSlotModel.setCreateTimeSlotData(new CreateTimeSlotData());
    }


    public void onDateSelect(DateSelectEvent selectEvent) {
        DefaultScheduleEvent scheduleEvent = new DefaultScheduleEvent("", selectEvent.getDate(), selectEvent.getDate());
        CreateTimeSlotData oldCreateTimeSlotData = createTimeSlotModel.getCreateTimeSlotData();
        createTimeSlotModel.setCreateTimeSlotData(new CreateTimeSlotData());
        createTimeSlotModel.setScheduleEvent(scheduleEvent);
        createTimeSlotModel.setSelectedDate(selectEvent.getDate());
        createTimeSlotModel.setSelectedTimeStart(selectEvent.getDate());
        createTimeSlotModel.setSelectedTimeEnd(new DateTime(selectEvent.getDate()).plusHours(1).toDate());
        createTimeSlotModel.getCreateTimeSlotData().setLocationName(oldCreateTimeSlotData.getLocationName());
        createTimeSlotModel.getCreateTimeSlotData().setPlace(oldCreateTimeSlotData.getPlace());
        createTimeSlotModel.getCreateTimeSlotData().setStreet(oldCreateTimeSlotData.getStreet());
    }


    public void onEventSelect(ScheduleEntrySelectEvent selectEvent) {
        ScheduleEvent scheduleEvent = selectEvent.getScheduleEvent();
        createTimeSlotModel.setScheduleEvent((DefaultScheduleEvent) scheduleEvent);
        CreateTimeSlotDataWrapper dataWrapper = (CreateTimeSlotDataWrapper) scheduleEvent.getData();
        createTimeSlotModel.setCreateTimeSlotData(dataWrapper.getCreateTimeSlotData());
        createTimeSlotModel.setSelectedDate(scheduleEvent.getStartDate());
        createTimeSlotModel.setSelectedTimeStart(scheduleEvent.getStartDate());
        createTimeSlotModel.setSelectedTimeEnd(scheduleEvent.getEndDate());
    }

    public void onEventMove(ScheduleEntryMoveEvent event) {
        ScheduleEvent scheduleEvent = event.getScheduleEvent();
        CreateTimeSlotDataWrapper dataWrapper = (CreateTimeSlotDataWrapper) scheduleEvent.getData();
        Date startDate = scheduleEvent.getStartDate();
        Date timeEnd = scheduleEvent.getEndDate();
        Interval i = new Interval(new DateTime(startDate), new DateTime(timeEnd));
        dataWrapper.getCreateTimeSlotData().setDateTimeInterval(i);
    }

    public void onEventResize(ScheduleEntryResizeEvent event) {
        ScheduleEvent scheduleEvent = event.getScheduleEvent();
        CreateTimeSlotDataWrapper dataWrapper = (CreateTimeSlotDataWrapper) scheduleEvent.getData();
        Date startDate = scheduleEvent.getStartDate();
        Date timeEnd = scheduleEvent.getEndDate();
        Interval i = new Interval(new DateTime(startDate), new DateTime(timeEnd));
        dataWrapper.getCreateTimeSlotData().setDateTimeInterval(i);
    }


    public List<ShowTimeSlotLocationData> searchLocationsBySearchTermAction(String query) {
        List<ShowTimeSlotLocationData> locationDataListShow = timeSlotVoteSearchService.findTimeSlotLocationsByCurrentMemberTimeSlotVotes(query);
        return locationDataListShow;
    }


    public void applySelectedLocationToNewTimeSlotData(SelectEvent selectEvent) {
        ShowTimeSlotLocationData selectedLocationShow = (ShowTimeSlotLocationData) selectEvent.getObject();
        createTimeSlotModel.getCreateTimeSlotData().setLocationName(selectedLocationShow.getName());
        createTimeSlotModel.getCreateTimeSlotData().setPlace(selectedLocationShow.getPlace());
        createTimeSlotModel.getCreateTimeSlotData().setStreet(selectedLocationShow.getStreet());
    }

    public DefaultScheduleEvent prepareAndGetNewTimeSlotAction() throws InvalidDateInvtervalException {
        CreateTimeSlotData createTimeSlotData = createTimeSlotModel.getCreateTimeSlotData();
        DefaultScheduleEvent scheduleEvent = createTimeSlotModel.getScheduleEvent();
        final Interval dateTimeInterval = getInterval();
        createTimeSlotData.setDateTimeInterval(dateTimeInterval);
        CreateTimeSlotDataWrapper createTimeSlotDataWrapper = new CreateTimeSlotDataWrapper(createTimeSlotData);
        scheduleEvent.setStartDate(dateTimeInterval.getStart().toDate());
        scheduleEvent.setEndDate(dateTimeInterval.getEnd().toDate());
        scheduleEvent.setData(createTimeSlotDataWrapper);
        scheduleEvent.setTitle("Learning Event @ " + createTimeSlotDataWrapper.getLocationName());
        return scheduleEvent;

    }

    private Interval getInterval() throws InvalidDateInvtervalException {
        final Date startDate = combineDateAndTime(createTimeSlotModel.getSelectedDate(), createTimeSlotModel.getSelectedTimeStart());
        final Date endDate = combineDateAndTime(createTimeSlotModel.getSelectedDate(), createTimeSlotModel.getSelectedTimeEnd());
        if (endDate.before(startDate)) {
            throw new InvalidDateInvtervalException("");
        }
        return new Interval(new DateTime(startDate), new DateTime(endDate));
    }


    private Date combineDateAndTime(Date date, Date time) {
        Date truncatedDate = DateUtils.truncate(date, Calendar.DATE);
        Calendar myCal1 = Calendar.getInstance();
        myCal1.setTime(time);
        DateTime dateTime = new DateTime(truncatedDate).plusHours(myCal1.get(Calendar.HOUR_OF_DAY)).plusMinutes(myCal1.get(Calendar.MINUTE));
        return dateTime.toDate();
    }

    public void startTimeAdjustedAction() {
        //this.createTimeSlotModel.setSelectedTimeEnd(plusOneHour(createTimeSlotModel.getSelectedTimeStart(), 1));
        this.adjustDuration();

    }

    public void endTimeAdjustedAction() {
        this.adjustDuration();
    }

    public void adjustDuration() {
        try {
            Period period = getInterval().toPeriod();
            this.createTimeSlotModel.setTimeDuration(period.getHours() + " h" + period.getMinutes() + " m");
        } catch (InvalidDateInvtervalException e) {
            // Nothing
            this.createTimeSlotModel.setTimeDuration(null);
        }
    }

    private Date plusOneHour(Date date, int amount) {
        return new DateTime(date).plusHours(amount).toDate();
    }
}
